/*===========================================
 * Source file Name : DocStructure.cpp
 * 
 * Role: 능동적으로 행동하는 Template Entity.
 * Revision By: 임 경택
 * Revision Date : 2007-02-03
 * History:
 * 	- GetTag 함수 추가. == Allblog 지원용
 *
=============================================*/


//#include "string"i	2007-12-23 이게 왜 들어가 있나? 여기에?
#include <string>
#include "DocStructure.h"
#define MAX 100

using namespace std;

DocStructure::DocStructure():imageMGR()
{
	this->count = 0;
}

DocStructure::DocStructure( const DocStructure& source )
{
	for ( int i = 0; i < MAX; i++ )
	{
		this->role[i] = source.role[i];
		this->start[i] = source.start[i];
		this->end[i] = source.end[i];
		this->imageMGR = source.imageMGR;
		(this->count)++;
	}
}

DocStructure::~DocStructure()
{
}

DocStructure& DocStructure::operator = ( const DocStructure& source )
{
	for ( int i = 0; i < MAX; i++ )
	{   
		this->role[i] = source.role[i];
		this->start[i] = source.start[i];
		this->end[i] = source.end[i];
		(this->count)++;
	}
	return (*this);
}

bool DocStructure::operator == ( const DocStructure& other )
{
	bool ret = true;

	for ( int i = 0; i < MAX; i++ )
	{
		if ( this->role[i] != other.role[i] ||
		     this->start[i] != other.start[i] ||
			 this->end[i] != other.end[i] )
		{
			ret = false;
			i = i + 30;
		}
	}

	return ret;
}


bool DocStructure::operator != ( const DocStructure& other )
{
	bool ret = false;

	for ( int i = 0; i < MAX; i++ )
	{
		if ( this->role[i] == other.role[i] &&
			 this->start[i] != other.start[i] &&
			 this->end[i] != other.end[i] )
		{
			ret = true;
		}
	}

	return ret;
}

int DocStructure::GetDesc(string link, string* document, string* ret )
{
	int retIndex = -1; 			
	ret->erase();

	// 일치하는 RoleSet을 검색한다.
	int i = 0;
	while ( i < MAX && this->role[i] != "itemDesc" )
	{
		i++;
	}

	int start = 0;
	int end = 0;

	// 검색된 RoleSet의 시작 태그와 끝 태그가 나타나는 지점을 찾아낸다.
	start = document->find( this->start[i] );
	end   = document->find( this->end[i]);

	// 검색이 올바르게 되었을 경우,
	if ( start > 0 && end > start )
	{
		start = start + (this->start[i]).length();	//태그가 시작된 위치에서 태그 자체의 길이를 더해서 Contents가 시작된 곳을 가르킨다.

		ret->assign( *document, start, end - start );	//document에서 태그가 시작된 곳부터 끝나는 곳까지 Contents를 잘라내어 리턴한다.

		start = 0;
		end   = 0;

		//Image를 추출해 Thumnail 이미지를 만든다.
		this->GetImageMGR().MakeThumbnail( *ret, link );


		
		//Description에 태그가 들어갈 경우, 태그를 제거한다.

		// < ~ > 사이에 없는 태그들을 일단 다 지운다.
		start = 0;
		while ( start != -1 )
		{
			start = (int) ret->find( "&amp;lt;" );
			if ( start > -1 )   ret->erase ( start, 8 );
		}
		//printf( " amplt delete \n" );

		start = 0;
		while ( start != -1 )
		{
			start = (int) ret->find( "&amp;gt;" );
			if ( start > -1 )   ret->erase ( start, 8 );
		}
		//printf( " ampgt delete \n" );

		// &amp;nbsp; 삭제
		start = 0;
		while ( start != -1 )
		{
			start = (int) ret->find( "&amp;nbsp;" );
			if ( start > -1 )	ret->erase ( start, 11 );
		}
		//printf(" ampnbsp delete \n");

		//&quot; 삭제
		start = 0;
		while ( start != -1 )
		{
			start = (int) ret->find( "&quot;" );
			if ( start > -1 )   ret->erase ( start, 6 );
		}
		//printf(" quot delete \n");

		// < ~ > 삭제하기
		start = 0;
		end = 0;
		int detectLoop = 0;
		while ( detectLoop < 200 && start != -1 && end != -1 )
		{
			start = (int) ret->find ( "&lt" );
			end   = (int) ret->find ( "&gt" );
			//printf( "\n\n>> < : %d   > : %d \n\n" , start, end );
			if ( start > -1 && end > -1 && end > start )    ret->erase ( start, end + 3 - start );
			detectLoop++;
		}
		//printf(" <> delete \n");

		// ; 삭제하기
		start = 0;
		while ( start != -1 )
		{
			start = (int) ret->find ( ";" );

			if ( start > -1 ) ret->erase ( start, 1 );
		}

		//문장 앞에 공백 문자들 삭제하기
		start = 0;
		while ( strncmp( &((*ret)[start]) , " ", 1 ) == 0 )
		{
			start++;
		}
		if ( start > 0 && ret->length() > 1)
		{
			ret->assign ( *ret, start, 1 );
		}
		while ( strncmp( &((*ret)[start]) , "\n", 1 ) == 0 )
		{
			start++;
		}
		if ( start > 0 && ret->length() > 1 )
		{
			ret->assign ( *ret, start, 1 );
		}



		if ( ret->length() > 250 ) // 추출된 자료가 1020Byte가 넘어갈 경우, 뒷부분을 잘라낸다.
		{
			ret->assign( *ret, 0, 250 );
			(*ret) += "...";
		}


		retIndex = end + (this->end[i]).length();	//종료태그가 시작된 위치에서 종료태그 자체의 길이를 더해서 다음 처리할 위치를 구한다.
	}
	//검색이 올바르지 않았을 경우 공백문자를 리턴한다.
	else
	{
		(*ret) = "";
	}	
	return retIndex;
}

int DocStructure::GetTag(string* document, int* count, string** tagSet )
{
	int retIndex = -1;
	*count = 0;
		
	int i = 0;
	while ( i < MAX && this->role[i] != string("tag") )
	{
		i++;
	}

	int start = 0;
	int ptr = 0;
	int end = 0;

	if ( document->length() > 0 )
	{
		start = (int) ( document->find( this->start[i] ) ) + (this->start[i]).length();
		end   = (int) ( document->find( this->end[i]) ) - 1;
		retIndex = (int)( ( this->end[i]).length()) + end + 1;

		//만약 tag의 시작과 끝의 태그가 발견되면,
		if ( start > 0 && end > 0 )
		{
			string tagStr;
			tagStr.assign( *document, start, end - start + 1);
			string backupTagStr = tagStr;

			while ( tagStr.length() > 0 )
			{
				ptr = (int) tagStr.find("/");
				if ( ptr > -1 )
				{
					tagStr.assign( tagStr, ptr + 1 , end - ptr + 1 );
				}
				else if ( ptr == -1 )
				{
					tagStr.erase();
				}
				(*count)++;
			}
			tagStr = backupTagStr;

			if ( *count > 0 )
			{
//				(*count)++;

				*tagSet = new string[ *count ];

				int startPtr = 0;
				int endPtr = 0;
				int tagSetCount = 0;
				while( tagStr.length() > 0 )
				{
					endPtr = (int) tagStr.find("/");
					if ( endPtr > -1 )
					{
						((*tagSet)[tagSetCount]).assign ( tagStr, startPtr, endPtr );
						tagStr.assign( tagStr, endPtr + 1, tagStr.length() - endPtr -1 );
						tagSetCount++;
					}
					else 
					{
						(*tagSet)[tagSetCount] = tagStr;
						tagSetCount++;
						tagStr.erase();
					}
				}
			}// count if end
		} // finded tag if end
	}// document length if end

	return retIndex;
}
					
		

int DocStructure::GetData(string role, string* document, string* ret )
{
	int retIndex = -1;
	ret->erase();

	// 일치하는 RoleSet을 검색한다.
	int i = 0;
	while ( i < MAX && this->role[i] != role )
	{
		i++;
	}

	int start = 0;
	int end = 0;

	start = document->find( this->start[i] );
	end   = document->find( this->end[i]);

	if ( start > 0 && end > start )
	{
		start = start + (this->start[i]).length();  //태그가 시작된 위치에서 태그 자체의 길이를 더해서 Contents가 시작된 곳을 가르킨다.
		ret->assign( *document, start, end - start );   //document에서 태그가 시작된 곳부터 끝나는 곳까지 Contents를 잘라내어 리턴한다.
		retIndex = end + (this->end[i]).length();
	}
	else
	{
		    (*ret) = "";
	}
	return retIndex;
}
	
	

#if 0
int main()
{
	DocStructure docStructure;

	docStructure.SetTemplate( "channel", "<channel>", "</channel>" );
	docStructure.SetTemplate( "item", "<item>", "</item>" );
	docStructure.SetTemplate( "tag", "<category>", "</category>" );
	docStructure.SetTemplate( "itemDesc", "<description>", "</description>" ); 

	string role("itemDesc");
	string document("start <channel> Channel Contents Channel Contents Channel Contents Channel Contents Channel Contents </channel><item> Item Contents<description>     <a herf= \"sdfsdjklsd\" > LinkLink </herf>1234567890 1234567890 </description> </item> <category> tag1/tag 2/tag3</category> end");

	string ret;
	
	int count = 0;
	string* tagSet = NULL;

	
	int processIndex = docStructure.GetData( role, &document, &ret );
	/*
	printf("\n%s", ret.c_str() );
	
	role = "item";
	document = document.assign( document, processIndex + 1, document.length() - processIndex );
	processIndex = docStructure.GetData( &role , &document, &ret );
	printf("\n%s", ret.c_str() );
*/
	return 0;
}

#endif
	
